# -*- coding: utf-8 -*-
# 姓名:谚语
# 开发时间:2022/10/30 9:23
from datetime import datetime
from dateutil.relativedelta import relativedelta

from flask import g, current_app
from flask_restful import Resource
from flask_restful.reqparse import RequestParser

from comment.modules import db
from comment.modules.deal_record import DealRecord
from comment.modules.funding_not_matched import Funding_not_matched
from comment.modules.invest_record import Invest_record
from comment.modules.product import Product
from comment.modules.product_rate import Product_rate
from comment.modules.user import User
from comment.modules.account import Account
from comment.utils.gen_trans_id import gen_trans_id
from financial.resources.transaction.const import DealType
from financial.resources.transaction.seralizer import InvestRecordPaginateSerializer


# 传入年利益 投资金额
def calculate_income(rate, amount):
    """计算每期收益"""
    # 年利益/百分化/12个月，保留位数
    return round(rate / 100 / 12 * amount, 2)


class Invest_Resource(Resource):
    """投资记录的资源类"""

    def get(self):
        """投资记录的列表"""
        # 接收参数
        rp = RequestParser()
        rp.add_argument('start')  # 起始时间
        rp.add_argument('end')  # 结束时间
        rp.add_argument('invest_type')  # 投资类型 初始值为0，0：购买中的计划，1：回款中的计划，2：已完成的计划
        rp.add_argument('curPage', required=True)  # 当前页号
        rp.add_argument('per_page', required=True)  # 每页显示的条数
        # 得到参数
        args = rp.parse_args()
        start = args.get('start')
        end = args.get('end')
        invest_type = 0 if args.get('invest_type') is None else int(args.get('invest_type'))
        cur_page = int(args.get('curPage'))
        page_size = int(args.get('per_page'))

        user_id = g.user_id
        # 得到一个查询对象
        q = Invest_record.query
        # 开始过滤: 第一个: 根据用户ID过滤
        q = q.filter(Invest_record.pUid == user_id)
        # 第二个过滤: 根据投资类型过滤
        q = q.filter(Invest_record.pStatus == invest_type)
        # 第三个过滤：根据起始时间和结束时间(得到时间区间)
        if start and end:
            # .cast(转换的数据, 转换的类型) 做类型转换
            q = q.filter(db.cast(Invest_record.pDate, db.DATE) >= db.cast(start, db.DATE)) \
                .filter(db.cast(Invest_record.pDate, db.DATE) <= db.cast(end, db.DATE))

        # 分页    .paginate(当前页, 一页显示多少条数据, 没有下一页或上一页时是否报错)
        data = q.paginate(cur_page, page_size, error_out=False)

        # 序列化(也就是转换成字典类型数据)  .to_dict()将JSON数据转换成字典类型数据
        data = InvestRecordPaginateSerializer(data).to_dict()

        return {'msg': 'success', 'data': data}

    def post(self):
        """新增投资或者购买理财产品"""
        # 定义
        rp = RequestParser()
        rp.add_argument('productId', required=True)  # 产品ID
        rp.add_argument('pAmount', required=True)  # 金额
        rp.add_argument('period', required=True)  # 期数
        rp.add_argument('discount', required=True)  # 抵扣金额
        # 获取
        args = rp.parse_args()
        product_id = int(args.productId)  # 产品id
        p_amount = int(args.pAmount)  # 购买金额
        period = int(args.period)  # 购买期数
        discount = int(args.discount)  # 抵扣金额

        user_id = g.user_id
        user = User.query.filter(User.id == user_id).first()  # 当前登录的用户

        # 查询产品对象
        product = Product.query.filter(Product.proId == product_id).first()

        # 查询产品对于的理财收益年利率，根据产品ID(产品编号) and 理财的期数(月)
        pro_rate = Product_rate.query.filter(Product_rate.productId == product_id) \
            .filter(Product_rate.month == period).first()

        # 计算每期收益(每个月的利息)    注意: 应传一个属性的值而不是一个对象
        income = calculate_income(pro_rate.incomeRate, p_amount)

        try:
            # 修改用户的资金账户数据
            # 查询用户资金账户
            user_account_query = Account.query.filter(Account.userId == user_id)  # 查询对象
            user_account = user_account_query.first()  # .first() 查出来是一个模型对象
            # 判断是否可以抵扣金额，每邀请一人可得到50代金券，每投资一次最多使用50抵扣金额
            cur_discount = 50 if user_account.discount >= 50 else 0
            _p_amount = p_amount - cur_discount  # 得到真正要支付的金额
            if user_account.balance >= _p_amount:  # 账户余额足够(账户余额大于需要支付的金额)
                before_balance = user_account.balance  # # 修改之前的账户余额
                cur_balance = user_account.balance - _p_amount  # 更新账户可用余额
                discount_balance = user_account.discount - cur_discount  # 跟新代金券总额
            else:  # 账户余额不足
                return {'message': '可用余额不足', 'code': 20005}
            # 当前这一次的投资总共要收到的利息      每期收益 * 购买期数
            interestTotal = income * period
            # 修改    [update 修改  不是属性而是一个函数]
            user_account_query.update({
                'balance': cur_balance,  # 账户可用余额
                'inverstmentA': user_account.inverstmentA + p_amount,  # 已投资总额
                'inverstmentW': user_account.inverstmentW + p_amount,  # 总计待收本金
                'frozen': user_account.frozen + _p_amount,  # 账户总计冻结总额
                'interestTotal': user_account.interestTotal + interestTotal,  # 总计待收利息
                'discount': discount_balance  # 代金券的总金额
            })

            # 新增投资记录
            # 生成投资记录的流水号(投资编号)
            invest_num = gen_trans_id(DealType.invest.name)
            # 是否使用代金券
            remark = "使用了50元代金券。" if cur_discount == 50 else '没有使用代金券'
            # 投资结束的时间  开始时间 + 投资期数（months期数）
            p_end_date = datetime.now() + relativedelta(months=period)
            # 精确的投资天数 = 投资结束时间 - 当前系统时间     days 精确到天的时间差
            invest_days = (p_end_date - datetime.now()).days
            # 用户投资记录表(产品id,用户id,加入日期,   到期日期,投资编号,投资金额,   收益率,选择期限,每月盈取利息,
            #             每月提取利息,可用余额,   冻结金额(付了多少钱),产品名称,   投资天数,投资用户名,   预期收益,状态,代金券是否使用)
            invest_record = Invest_record(pProductId=product_id, pUid=user_id, pBeginDate=datetime.now(),
                                          pEndDate=p_end_date, pSerialNo=invest_num, pAmount=p_amount,
                                          pEarnings=pro_rate.incomeRate, pDeadline=period, pMonthInterest=income,
                                          pMonthlyExtractInterest=income, pAvailableBalance=user.accountInfo.balance,
                                          pFrozenMoney=_p_amount, pProductName=product.productName,
                                          pDeadlineAsDay=invest_days, username=user.username,
                                          pProspectiveEarnings=interestTotal, pStatus=0, pRemark=remark)

            db.session.add(invest_record)  # 信息添加如数据库
            db.session.flush()  # 刷新数据将数据暂时提交至数据库缓存中

            # 新增待匹配的资金
            # 待匹配资金表的模型类(投资记录,待匹配金额,    待匹配的权重(资金【最终匹配的金额】越大优先级率越大),匹配状态)
            not_matched = Funding_not_matched(fInvestRecordId=invest_record.pId, fNotMatchedMoney=p_amount,
                                              fFoundingWeight=1, matchedStatus=0)
            db.session.add(not_matched)

            # 新增交易记录
            # 生成交易记录的流水号
            deal_num = gen_trans_id(DealType.invest.name)
            # 交易记录的模型类(用户id, 交易记录的ID(投资记录主键), 收付,1表示接收,2表示付款,
            #               交易记录的流水号, 交易状态,0代表交易失败,1代表交易成功, 交易前金额，m,
            #               金额, 交易后金额, 交易详情,      交易类型)
            deal_record = DealRecord(aUserId=user_id, pId=invest_record.pId, aReceiveOrPay=1,
                                     aTransferSerialNo=deal_num, aTransferStatus=1, aBeforeTradingMoney=before_balance,
                                     aAmount=p_amount, aAfterTradingMoney=cur_balance, aDescreption='投资产品购买',
                                     aType=DealType.invest.value)
            db.session.add(deal_record)

            db.session.commit()
            return {'msg': 'success', 'data': ''}
        except Exception as e:
            current_app.logger.error(e)  # 将错误信息打印至日志里
            db.session.rollback()  # 回滚


if __name__ == '__main__':
    print(calculate_income(12, 10000))
